
#pragma once

#include <stdint.h>
#include <stdlib.h>

#define MD2_DIGEST_SIZE 16
#define MD2_BLOCK_SIZE 16
/* For backwards compatibility */
#define MD2_DATA_SIZE MD2_BLOCK_SIZE

class CMD2
{
private:
    struct md2_ctx
    {
        uint8_t C[MD2_BLOCK_SIZE];
        uint8_t X[3 * MD2_BLOCK_SIZE];
        uint8_t block[MD2_BLOCK_SIZE]; /* Block buffer */
        unsigned index;               /* Into buffer */
    } ctx_;

    void md2_init();

    void md2_update(size_t length, const uint8_t *data);

    void md2_digest(uint8_t *digest);

    void md2_transform(const void*, const uint8_t *data);
public:
    static const size_t OUTPUT_SIZE         = 16;
    static const size_t BLOCK_SIZE          = 16;
    static const size_t OUTPUT_HMAC_SIZE    = 16;

    CMD2() {
        md2_init();
    }
    CMD2& Write(const unsigned char* data, size_t len) {
        md2_update(len, (uint8_t*)data);
        return *this;
    }
    void Finalize(unsigned char hash[MD2_DIGEST_SIZE]) {
        md2_digest((uint8_t*)hash);
    }
    CMD2& Reset() {
        md2_init();
		return *this;
    }
};